package com.example.version.controll.controller;

import com.example.version.controll.model.*;
import com.example.version.controll.eo.TypeEO;
import com.example.version.controll.poi.model.*;
import com.example.version.controll.poi.util.*;
import com.example.version.controll.util.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@RestController
public class VersionController {

    @GetMapping("config/load")
    public ConfigDTO loadConfig() throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        return FileUtil.configDTO;
    }

    @PostMapping("config/add")
    public void addConfig(@RequestBody RepositoryConfig repositoryConfig) throws Exception {
        if (repositoryConfig != null) {
            if (!StringUtils.hasText(repositoryConfig.getName())) {
                String gitUrl = repositoryConfig.getGitUrl();
                String name = gitUrl.substring(gitUrl.lastIndexOf("/") + 1, gitUrl.lastIndexOf("."));
                repositoryConfig.setName(name);
            }
            List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
            GitUtil gitUtil = FileUtil.gitUtilMap.get(repositoryConfig.getName());
            if (gitUtil != null) {
                return;
            }
//            BatUtil.generateBat(repositoryConfig, true);
            repositoryList.add(repositoryConfig);
//            FileUtil.writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(FileUtil.configDTO));
        }
    }

    @PostMapping("config/update")
    public void updateConfig(@RequestBody RepositoryConfig repositoryConfig) throws Exception {
        if (!StringUtils.hasText(repositoryConfig.getBranch())) {
            return;
        }
        if (!StringUtils.hasText(repositoryConfig.getName())) {
            return;
        }
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        GitUtil gitUtil = FileUtil.gitUtilMap.get(repositoryConfig.getName());
        if (gitUtil == null) {
            return;
        }
        for (RepositoryConfig config : repositoryList) {
            if (config.getName().equals(repositoryConfig.getName())) {
                config.setBranch(repositoryConfig.getBranch());
//                BatUtil.generateBat(repositoryConfig, true);
//                FileUtil.writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(FileUtil.configDTO));
                FileUtil.reloadConfig();
                return;
            }
        }
    }

    @GetMapping("config/del")
    public void updateConfig(@RequestParam("name") String name) throws Exception {
        if (!StringUtils.hasText(name)) {
            return;
        }
        // 删除config.txt
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        FileUtil.configDTO.setRepositoryList(repositoryList.stream().filter(x -> !name.equals(x.getName())).collect(Collectors.toList()));
//        FileUtil.writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(FileUtil.configDTO));
//        // 删除buildCache.txt
//        FileUtil.projectDTOMap.remove(name);
//        FileUtil.writeContent2File(PathManagerUtil.configPath, JsonUtil.toJsonString(FileUtil.projectDTOMap));
        FileUtil.reloadConfig();
        // 删除git项目和git脚本
        FileUtil.delProject(PathManagerUtil.gitDataPath + name);
        FileUtil.delProject(PathManagerUtil.batPath + name);
    }

    @GetMapping("generate")
    public String generateBat() throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        if (CollectionUtils.isNotEmpty(repositoryList)) {
            for (RepositoryConfig repositoryConfig : repositoryList) {
                BatUtil.generateBat(repositoryConfig, true);
            }
        }
        return "";
    }

    @GetMapping("cloneBat")
    public String cloneBat() throws Exception {
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        for (RepositoryConfig repositoryConfig : repositoryList) {

        }
        return "";
    }

    @GetMapping("commitBat")
    public String commitBat() throws Exception {
        BatUtil.runBat(TypeEO.COMMIT);
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            GitUtil gitUtil = repositoryConfig.getGitUtil();
            gitUtil.batchCommit("版本号");
        }
        return "";
    }

    @GetMapping("updateLocalBat")
    public String updateLocalBat() throws Exception {
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            GitUtil gitUtil = repositoryConfig.getGitUtil();
            gitUtil.batchUpdate();
        }
        return "";
    }

    @GetMapping("build/find")
    public List<ProjectDTO> findBuildFile() throws Exception {
        FileUtil.maxVersion = "0.0.0";
        FileUtil.findBuild();
        FileUtil.checkType();
        List<ProjectDTO> projectDTOS = new ArrayList<>();
        Set<String> strings = FileUtil.projectDTOMap.keySet();
        for (String string : strings) {
            ProjectDTO projectDTO = FileUtil.projectDTOMap.get(string);
            ProjectVersion versionByName = FileUtil.findVersionByName(string);
            projectDTO.setVersion(versionByName);
            projectDTOS.add(projectDTO);
        }
        Map<String, Integer> sortMap = new HashMap<>();
        for (int i = 0; i < FileUtil.gradleSort.size(); i++) {
            String s = FileUtil.gradleSort.get(i);
            sortMap.put(s, i + 1);
        }
        for (int i = 0; i < projectDTOS.size(); i++) {
            ProjectDTO projectDTO = projectDTOS.get(i);
            if (projectDTO.getSort() == null) {
                Integer integer = sortMap.get(projectDTO.getName());
                if (integer == null) {
                    projectDTO.setSort(30 + i);
                } else {
                    projectDTO.setSort(integer);
                }
            }
        }
        projectDTOS = projectDTOS.stream().sorted(Comparator.comparing(ProjectDTO::getSort)).collect(Collectors.toList());
        return projectDTOS;
    }

    @GetMapping("build/version")
    public String findBuildVersion() throws Exception {
        return JsonUtil.toJsonString(FileUtil.findVersion());
    }

    @GetMapping("build/max/version")
    public String findBuildMaxVersion() throws Exception {
        return FileUtil.maxVersion + "-SNAPSHOT";
    }

    @PostMapping("branchs/remote")
    public List<String> findBuildMaxVersion(@RequestBody RepositoryConfig config) throws Exception {
        return GitUtil.getRemoteBranchs(config.getGitUrl());
    }

    @GetMapping("build/upload")
    public String upload() throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        List<SortGradle> sortGradles = new ArrayList<>();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            GitUtil gitUtil = repositoryConfig.getGitUtil();
            gitUtil.batchUpdate();
            List<ProjectDTO> projectList = repositoryConfig.getProjectList();
            for (ProjectDTO projectDTO : projectList) {
                if ("api".equals(projectDTO.getType())) {
                    SortGradle sortGradle = new SortGradle();
                    sortGradle.setSort(projectDTO.getSort());
                    sortGradle.setRepositoryConfig(repositoryConfig);
                    sortGradle.setProjectDTO(projectDTO);
                    sortGradles.add(sortGradle);
                }
            }
        }
        sortGradles = sortGradles.stream().sorted(Comparator.comparing(SortGradle::getSort)).collect(Collectors.toList());
        for (SortGradle sortGradle : sortGradles) {
            System.out.println("######################## 开始gradle upload " + sortGradle.getProjectDTO().getName() + " upload顺序" + sortGradle.getSort());
            BatUtil.runBat(TypeEO.GRADLE, sortGradle.getRepositoryConfig(), sortGradle.getProjectDTO().getName());
            System.out.println("######################## gradle upload 完成" + sortGradle.getProjectDTO().getName() + " upload顺序" + sortGradle.getSort() + "\r\n");
        }
        return "";
    }

    @GetMapping("build/upload/{projectName}")
    public String upload(@PathVariable("projectName") String projectName) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        ProjectDTO projectDTO = FileUtil.projectDTOMap.get(projectName);
        if (projectDTO == null) {
            return "";
        }
        GitUtil gitUtil = FileUtil.gitUtilMap.get(projectDTO.getProjectName());
        gitUtil.batchUpdate();
        System.out.println("######################## 开始gradle upload " + projectDTO.getName());
        BatUtil.runBat(TypeEO.GRADLE, gitUtil.getRepositoryConfig(), projectDTO.getName());
        System.out.println("######################## gradle upload 完成" + projectDTO.getName());
        return "";
    }

    @GetMapping("build/replace/{newVersion}")
    public String replaceBuildVersion(@PathVariable("newVersion") String newVersion) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        List<RepositoryConfig> repositoryList = FileUtil.configDTO.getRepositoryList();
        List<SortGradle> sortGradles = new ArrayList<>();
        for (RepositoryConfig repositoryConfig : repositoryList) {
            GitUtil gitUtil = repositoryConfig.getGitUtil();
            gitUtil.batchUpdate();
            List<ProjectDTO> projectList = repositoryConfig.getProjectList();
            List<String> path = new ArrayList<>();
            for (ProjectDTO projectDTO : projectList) {
                FileUtil.replaceBomVersionByName(newVersion, projectDTO.getName());
                if ("api".equals(projectDTO.getType())) {
                    SortGradle sortGradle = new SortGradle();
                    sortGradle.setSort(projectDTO.getSort());
                    sortGradle.setRepositoryConfig(repositoryConfig);
                    sortGradle.setProjectDTO(projectDTO);
                    sortGradles.add(sortGradle);
                }
                path.add(projectDTO.getBuildAbsolutePath());
            }
            gitUtil.batchCommit(newVersion, path.stream().toArray(String[]::new));
        }
        sortGradles = sortGradles.stream().sorted(Comparator.comparing(SortGradle::getSort)).collect(Collectors.toList());
        for (SortGradle sortGradle : sortGradles) {
            System.out.println("######################## 开始gradle upload " + sortGradle.getProjectDTO().getName() + " upload顺序" + sortGradle.getSort());
            BatUtil.runBat(TypeEO.GRADLE, sortGradle.getRepositoryConfig(), sortGradle.getProjectDTO().getName());
            System.out.println("######################## gradle upload 完成" + sortGradle.getProjectDTO().getName() + " upload顺序" + sortGradle.getSort() + "\r\n");
        }
        return "";
    }

    @GetMapping("build/replace/{newVersion}/{projectName}")
    public String replaceBuildVersion(@PathVariable("newVersion") String newVersion, @PathVariable("projectName") String projectName) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        ProjectDTO projectDTO = FileUtil.projectDTOMap.get(projectName);
        if (projectDTO == null) {
            return "";
        }
        GitUtil gitUtil = FileUtil.gitUtilMap.get(projectDTO.getProjectName());
        gitUtil.batchUpdate();
        FileUtil.replaceBomVersionByName(newVersion, projectDTO.getName());
        gitUtil.batchCommit(newVersion, projectDTO.getBuildAbsolutePath());
        return "";
    }

    @GetMapping("tag/del/{projectName}/{tagName}")
    public void findProjectAllTags(@PathVariable("projectName") String projectName
            , @PathVariable("tagName") String tagName) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        GitUtil gitUtil = FileUtil.gitUtilMap.get(projectName);
        gitUtil.delTag(tagName);
    }

    @GetMapping("tag/list/{projectName}")
    public List<String> findProjectAllTags(@PathVariable("projectName") String projectName) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        GitUtil gitUtil = FileUtil.gitUtilMap.get(projectName);
        return gitUtil.getAllTags().stream().map(x -> x.getName().replace("refs/tags/", "")).sorted(((o1, o2) -> o2.compareTo(o1))).collect(Collectors.toList());
    }

    @PostMapping("tag/create")
    public void createTag(@RequestBody TagDTO tagDTO) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        tagCreate(tagDTO);
    }

    private void tagCreate(TagDTO tagDTO) throws GitAPIException, IOException {
        GitUtil gitUtil = FileUtil.gitUtilMap.get(tagDTO.getProjectName());
        gitUtil.createPushTag(tagDTO.getBranch(), tagDTO.getTagName());
    }

    @PostMapping("tags/create")
    public void createTags(@RequestBody List<TagDTO> tagDTO) throws Exception {
        if (FileUtil.configDTO == null) {
            FileUtil.initConfig();
        }
        for (TagDTO dto : tagDTO) {
            tagCreate(dto);
        }
    }

}
